﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.ComponentModel.DataAnnotations.Schema;
using System.Globalization;
using System.Reflection;
using System.Text.Json.Serialization;
using XYAC.Framework.MonitorTireMaterialManual.Entities;
using XYAC.Framework.MonitorTireMaterialManual.Extensions;
using XYAC.Framework.MonitorTireMaterialManual.IServices;
using XYAC.Framework.MonitorTireMaterialManual.OracleRemoteDB;

namespace XYAC.Framework.MonitorTireMaterialManual.Services
{
    public class YB_TechnologyService : ServiceBase<int, OracleMesContext>, IYB_TechnologyService
    {

        /// <summary>
        /// Ctor.
        /// </summary>
        /// <param name="appConfig"></param>
        /// <param name="logger"></param>
        /// <param name="provider"></param>
        public YB_TechnologyService(IOptionsMonitor<AppConfig> appConfig, ILogger logger, IServiceProvider provider) : base(appConfig, logger, provider)
        {
            this.Db = provider.GetService<OracleMesContext>();
            this.Logger = logger;
            this.AppConfig = appConfig;
            this.provider = provider;
        }

        public OracleMesContext Db { get; }
        public Dictionary<YB_Technology_Header, IEnumerable<YB_Technology_Line>> GetAllSpec(string detectMachineNo = null)
        {
            // 先获取所有匹配的头信息
            IQueryable<YB_Technology_Header> headers = Db.YB_Technology_Header;
            if (detectMachineNo != null)
            {
                headers = headers.Where(h => h.EQP_TYPE == detectMachineNo);//使用机台类型判断规格数据
            }

            var headerIds = headers.Select(h => new Nullable<long>(h.LJ_ID)).ToList();

            // 获取所有匹配的行信息
            var lines = Db.YB_Technology_Line
                           .Where(l => headerIds.Contains(l.RECIPE_ID))
                           .ToList();

            // 将结果构造成字典
            var result = headers.ToDictionary(
                header => header,
                header => lines.Where(line => line.RECIPE_ID == header.ID).AsEnumerable()
            );

            return result;
        }


        //机台编号
        //public string MachineNo { get; set; }
        //public string MachineType { get; set; }
        private ILogger Logger { get; set; }
        public IOptionsMonitor<AppConfig> AppConfig { get; }

        private IServiceProvider provider;

        public KeyValuePair<YB_Technology_Header, IEnumerable<YB_Technology_Line>> From(SpecInfo spec)
        {
            YB_Technology_Header header = new YB_Technology_Header()
            {
                //EQP = machineNo,
                BOM_NAME = spec.ProfileName,
                IS_ACTIVE = "1",
                BOM_REVSION = "",
                CREATION_DATE = DateTime.Now,
                //EQP_TYPE = AppConfig.CurrentValue.DetectionMachineNo,//存入机台类型
                //EQP = this.AppConfig.DetectionMachineNo
            };
            // 获取 SpecInfo 类的所有属性
            PropertyInfo[] properties = typeof(SpecInfo).GetProperties();

            // 创建 YB_Technology_Line 实例列表
            List<YB_Technology_Line> yBList = new List<YB_Technology_Line>();

            // 遍历 SpecInfo 的每个属性
            foreach (var prop in properties)
            {
                // 检查是否有 NotMapped 或 JsonIgnore 属性
                var notMappedAttr = (NotMappedAttribute)Attribute.GetCustomAttribute(prop, typeof(System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute));
                var jsonIgnoreAttr = (JsonIgnoreAttribute)Attribute.GetCustomAttribute(prop, typeof(JsonIgnoreAttribute));

                if (notMappedAttr != null || jsonIgnoreAttr != null)
                {
                    // 如果存在，跳过这个属性
                    continue;
                }
                // 创建 YB_Technology_Line 实例
                YB_Technology_Line yB = new YB_Technology_Line
                {
                    RECIPE_ID = header.ID, // 假设 RecipeId 是 1
                    CREATION_DATE = DateTime.Now,
                    ATTRIBUTE_CODE = prop.Name, // 属性名作为 AttributeCode
                    ATTRIBUTE_VALUE = prop.GetValue(spec, null)?.ToString(), // 属性值作为 AttributeValue
                    ATTRIBUTE_NAME = prop.Name // 属性名作为 AttributeName
                };

                // 将 YB_Technology_Line 实例添加到列表
                yBList.Add(yB);
            }
            return new KeyValuePair<YB_Technology_Header, IEnumerable<YB_Technology_Line>>(header, yBList);
        }



        private CrcCalculator _crcCalculator = new CrcCalculator();


        public SpecInfo ToSpecInfo(YB_Technology_Header header, IEnumerable<YB_Technology_Line> lines)
        {

            // 创建一个新的 SpecInfo 实例
            SpecInfo spec = new SpecInfo();
            spec.ProfileName = header.BOM_NAME;
            // 获取 SpecInfo 类的所有属性
            PropertyInfo[] properties = typeof(SpecInfo).GetProperties();

            // 创建一个字典用于快速查找 SpecInfo 属性
            Dictionary<string, PropertyInfo> propertyMap = properties.ToDictionary(p => p.Name);

            // 遍历 YB_Technology_Line 列表，设置 SpecInfo 属性值
            #region SetValues
            foreach (var line in lines)
            {
                if (propertyMap.ContainsKey(line.ATTRIBUTE_NAME))
                {
                    PropertyInfo property = propertyMap[line.ATTRIBUTE_NAME];


                    // 获取属性的基础类型（如果是可空类型）
                    Type propertyType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;

                    if (property.Name == "Id")
                    {
                        continue;
                    }
                    // 根据属性类型将值转换并设置到 SpecInfo 对象中
                    if (propertyType == typeof(int))
                    {
                        property.SetValue(spec, line.ATTRIBUTE_VALUE == null ? (int?)null : int.Parse(line.ATTRIBUTE_VALUE), BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                    }
                    else if (propertyType == typeof(short))
                    {
                        property.SetValue(spec, line.ATTRIBUTE_VALUE == null ? (short?)null : short.Parse(line.ATTRIBUTE_VALUE), BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                    }
                    else if (propertyType == typeof(long))
                    {
                        property.SetValue(spec, line.ATTRIBUTE_VALUE == null ? (long?)null : long.Parse(line.ATTRIBUTE_VALUE), BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                    }
                    else if (propertyType == typeof(bool))
                    {
                        property.SetValue(spec, line.ATTRIBUTE_VALUE == null ? (bool?)null : bool.Parse(line.ATTRIBUTE_VALUE), BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                    }
                    else if (propertyType == typeof(byte))
                    {
                        property.SetValue(spec, line.ATTRIBUTE_VALUE == null ? (byte?)null : byte.Parse(line.ATTRIBUTE_VALUE), BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                    }
                    else if (propertyType == typeof(double))
                    {
                        property.SetValue(spec, line.ATTRIBUTE_VALUE == null ? (double?)null : double.Parse(line.ATTRIBUTE_VALUE), BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                    }
                    else if (propertyType == typeof(float))
                    {
                        property.SetValue(spec, line.ATTRIBUTE_VALUE == null ? (float?)null : float.Parse(line.ATTRIBUTE_VALUE), BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                    }
                    else if (propertyType == typeof(string))
                    {
                        var attr = (NullReplaceAttribute)Attribute.GetCustomAttribute(property, typeof(NullReplaceAttribute));
                        if (attr != null && line.ATTRIBUTE_VALUE == null)
                        {
                            property.SetValue(spec, line.ATTRIBUTE_VALUE == null ? attr.NullReplaceValue : line.ATTRIBUTE_VALUE, BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                        }
                        else
                        {
                            property.SetValue(spec, line.ATTRIBUTE_VALUE, BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                        }
                    }
                    else if (propertyType == typeof(decimal))
                    {
                        property.SetValue(spec, line.ATTRIBUTE_VALUE == null ? (decimal?)null : decimal.Parse(line.ATTRIBUTE_VALUE), BindingFlags.Default, null, null, CultureInfo.InvariantCulture);
                    }
                    // 可以根据需要添加更多类型的转换
                }
            }
            #endregion
            //spec.Hash = _crcCalculator.ComputeCrc128(JsonSerializeHelper.SerializeObjectToJson(spec)).ToString();
            return spec;

        }

        /// <summary>
        /// 更新标记状态
        /// </summary>
        /// <param name="state"></param>
        /// <param name="deleteFlags"></param>
        /// <returns></returns>
        internal int UpdateFlag(string state, long[] deleteFlags)
        {
            var headers = this.Db.YB_Technology_Header.Where(T => deleteFlags.Contains(T.ID));
            headers.ForEachAsync(T => T.RECEIVE_FLAG = state);
            this.Db.UpdateRange(headers);
            return this.Db.SaveChanges();
        }


        /// <summary>
        ///  插入指定机台规格名称数据
        /// </summary>
        /// <param name="keyValuePair"></param>
        /// <returns></returns>
        internal int AddSpecAllInfo(KeyValuePair<YB_Technology_Header, IEnumerable<YB_Technology_Line>> keyValuePair)
        {
            int ret = 0;
            using (var transcation = this.Db.Database.BeginTransaction())
            {
                try
                {
                    this.Db.YB_Technology_Header.Add(keyValuePair.Key);

                    var tempRet = this.Db.SaveChanges();
                    foreach (var line in keyValuePair.Value)
                    {
                        line.RECIPE_ID = keyValuePair.Key.ID;
                    }
                    this.Db.YB_Technology_Line.AddRange(keyValuePair.Value);
                    tempRet += this.Db.SaveChanges();
                    transcation.Commit();
                    ret = tempRet;
                }
                catch (Exception ex)
                {
                    Logger.LogError("新增规格数据失败", ex);
                    transcation.Rollback();
                }
            }
            return ret;
        }

        internal int UpdateFlag(string updateFlag, int ljId)
        {
            var header = this.Db.YB_Technology_Header.FirstOrDefault(T => T.ID == ljId);
            if (header is not null)
            {
                header.RECEIVE_FLAG = updateFlag;
            }
            this.Db.Update(header);
            return this.Db.SaveChanges();

        }




        /// <summary>
        /// 获取指定机台规格名称数据
        /// </summary>
        /// <param name="detectingMachineNo"></param>
        /// <param name="typeName"></param>
        /// <returns></returns>
        internal KeyValuePair<YB_Technology_Header, List<YB_Technology_Line>> GetBySpecName(string detectingMachineNo, string typeName)
        {
            var header = this.Db.YB_Technology_Header.FirstOrDefault(T => T.EQP_TYPE == detectingMachineNo && T.BOM_NAME == typeName);
            if (header is not null)
            {
                var lines = this.Db.YB_Technology_Line.Where(T => T.RECIPE_ID == header.ID).ToList();
                return new KeyValuePair<YB_Technology_Header, List<YB_Technology_Line>>(header, lines);
            }
            else
            {
                return new KeyValuePair<YB_Technology_Header, List<YB_Technology_Line>>(null, null);
            }
        }

        /// <summary>
        /// 更新规格信息
        /// </summary>
        /// <param name="keyValuePair"></param>
        /// <returns></returns>
        internal int UpdateSpecAllInfo(KeyValuePair<YB_Technology_Header, IEnumerable<YB_Technology_Line>> keyValuePair)
        {
            int ret = 0;
            if (keyValuePair.Key != null && keyValuePair.Value != null)
            {
                using (var transcation = this.Db.Database.BeginTransaction())
                {
                    try
                    {

                        this.Db.Update(keyValuePair.Key);
                        this.Db.UpdateRange(keyValuePair.Value);
                        var tempRet = this.Db.SaveChanges();
                        transcation.Commit();
                        ret = tempRet;
                    }
                    catch (Exception ex)
                    {
                        Logger.LogError("更新规格数据失败", ex);
                        transcation.Rollback();
                    }
                }
            }
            return ret;
        }
    }
}
